// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

const { ccclass, property } = cc._decorator;

@ccclass
export default class GridSetPhrase {


    private GRID_WIDTH: number = 0;
    private GRID_HEIGHT: number = 0;
    private CELL_HEIGHT: number = 0;

    // private GRID_PIXEL_WIDTH: number = 0;
    // private GRID_PIXEL_HEIGHT: number = 0;

    private isReset: boolean = false;


    private shuxiangChao = [];
    private henxiangChao = [];
    public cells: string[][] = [];
    public cellsNode: cc.Node[][] = [];
    // private selectList = [];

    private posX: number = 100;
    private posY: number = -1;

    private left: boolean = false;
    private right: boolean = false;

    private finfishCallBack = null;

    constructor() {

    }

    /**
     * 
     * @param GRID_WIDTH 网格宽度 如6*6  传6
     * @param GRID_HEIGHT 网格高度
     * @param CELL_WIDTH 一个字的宽度 70*70像素 
     */
    public init(GRID_WIDTH, GRID_HEIGHT, CELL_HEIGHT) {
        this.GRID_HEIGHT = GRID_HEIGHT;
        this.GRID_WIDTH = GRID_WIDTH;
        this.CELL_HEIGHT = CELL_HEIGHT

        // this.GRID_PIXEL_WIDTH = this.GRID_WIDTH * this.CELL_WIDTH;
        // this.GRID_PIXEL_HEIGHT = this.GRID_HEIGHT * this.CELL_WIDTH;

        for (var i = 0; i < GRID_HEIGHT; i++) {
            this.cells[i] = [];
            this.cellsNode[i] = [];
            for (var j = 0; j < GRID_WIDTH; j++) {
                this.cells[i][j] = ""
                this.cellsNode[i][j] = null;
            }
        }
    }

    public reset() {
        for (var i = 0; i < this.GRID_HEIGHT; i++) {
            this.cells[i] = [];
            this.cellsNode[i] = [];
            for (var j = 0; j < this.GRID_WIDTH; j++) {
                this.cells[i][j] = ""
                this.cellsNode[i][j] = null;
            }
        }
    }


    /**新手引导 成语数据 */
    public getNewUserList(data) {
        let newUserType = [{ fangxiang: "right", hard: 4 }, { fangxiang: "left", hard: 1 }, { fangxiang: "left", hard: 0 }]
        this.reset();
        let r;
        for (let i = 0; i < data.length; i++) {
            if (newUserType[i]["fangxiang"] == "left") {
                this.left = true;
                this.right = false;
            } else {
                this.left = false;
                this.right = true;
            }
            this.initList();
            let f = (i) => {
                r = newUserType[i]["hard"]
                if (this.left) {
                    //横向
                    this.henxiangChao.push(newUserType[i]["hard"])
                    r = this.henxiangChao.pop();
                    //console.log("横向几号", r)
                    let isOk = true;
                    if (isOk) {
                        //成功确认横向
                        this.addList("LR", r, data[i])
                    }
                } else if (this.right) {
                    //竖向
                    this.shuxiangChao.push(newUserType[i]["hard"])
                    r = this.shuxiangChao.pop();
                    //console.log("竖向几号", r)
                    data[i].reverse();
                    this.addList("UD", r, data[i])
                } else {
                    //console.log("当前词组无位置加入", data[i][0])
                }
            }
            f(i);
            //console.log(i)
        }

        //console.log(this.cells);
        return this.cells;
    }

    /**
     * 
     * @param data 成语数据 如：data = [["1", "1", "1", "1"], ["2", "2", "2", "2"]]
     * @returns 
     */
    public getList(data) {
        this.reset();
        let r;
        console.time("开始");

        for (let i = 0; i < data.length; i++) {
            this.left = true;
            this.right = true;
            let index = 0;
            if (i == 0) {
                this.left = true;
                index = 0.6;
            } else if (i == 1) {
                this.left = false;
                index = 0.1
            }

            this.initList();
            let f = (fangxiang = 0) => {
                r = Math.random();
                if (fangxiang != 0) {
                    r = fangxiang
                }
                if (r > 0.5 && this.left) {
                    //横向

                    this.henxiangChao = this.shuffle(this.henxiangChao);
                    r = this.henxiangChao.pop();
                    //console.log("横向几号1", r)
                    while ((r || r == 0) && r + data[i].length > this.GRID_WIDTH) {
                        //超过横向
                        r = this.henxiangChao.pop();
                        //console.log("横向取出r", r)
                    }

                    if (!(r || r == 0)) {

                        if (this.henxiangChao.length == 0) {
                            this.left = false;
                            //console.log("重新开始")
                            f(0.1)
                        }
                        return
                    }

                    //console.log("横向几号2", r)
                    let isOk = true;
                    for (let j = r; j < r + data[i].length; j++) {
                        if (!this.searchList(j)) {
                            isOk = false;
                            break;
                        }
                    }

                    if (isOk) {
                        //成功确认横向
                        this.addList("LR", r, data[i])
                    } else {
                        if (this.henxiangChao.length == 0) {
                            //console.log("重新开始")

                            this.left = false;
                            f(0.1)
                            //重新确认方向
                        } else {

                            //console.log("重新开始左")

                            f(0.6)
                        }
                    }

                } else if (this.right && r <= 0.5) {
                    //竖向

                    this.shuxiangChao = this.shuffle(this.shuxiangChao)
                    r = this.shuxiangChao.pop();
                    //console.log("竖向几号1", r)
                    let height = this.searchHeight(r)
                    //console.log("第一次height", height)
                    while (((r != null && height != null && height + data[i].length > this.GRID_HEIGHT) || !this.searchLow(r)) || (height == null && this.shuxiangChao.length > 0)) {
                        //超过顶
                        r = this.shuxiangChao.pop();

                        height = this.searchHeight(r)
                        //console.log("竖向取出r", r, height)
                    }

                    //console.log("竖向几号2", r, height)

                    if (!(r || r == 0) || !(height || height == 0)) {
                        this.right = false;
                        //console.log("重新开始")
                        f(0.6)

                        return
                    }
                    data[i].reverse();
                    this.addList("UD", r, data[i])
                } else {
                    //console.log("当前词组无位置加入", data[i][0])
                    this.isReset = true;
                    return
                }
            }
            f(index);
            if (this.isReset) {
                break;
            }
            //console.log(i)
        }

        console.timeEnd("开始");
        if (this.isReset) {
            this.isReset = false;
            console.time("开始");
            return this.getList(data);
        }
        // console.log("list")
        // console.log(this.cells);
        return this.cells;
    }

    /**
     * 
     * @param data 二维数组[[],[],[]]
     */
    public setCellsNode(data) {
        this.cellsNode = data;
    }

    /**
     * 
     * @param data 玩家选中的网格位置 如左下角第一个 [cc.v2(0,0),cc.v2(0,1),cc.v2(0,2),]
     * @returns 
     */
    public checkAnswer(data, cb?) {
        if (cb) {
            this.finfishCallBack = cb;
        }
        let success = (data, isX, isY) => {
            //消除  下落

            for (let i = data.length - 1; i >= 0; i--) {
                let va = data.pop();
                let node = this.selectCell(va);
                this.cells[va.x][va.y] = "";
                this.cellsNode[va.x][va.y] = null;
                cc.tween(node).to(0.2, { scaleX: 0, scaleY: 0 }).start();
                setTimeout(() => {
                    node.destroy();
                }, 300);
            }
            // setTimeout(() => {
            this.checkDown(isX, isY);
            // }, 500);
        }

        let isX = true;
        let isY = true;
        let x1 = data[0].x
        let x2 = data[0].y
        this.posY = data[0].y;
        this.posX = data[0].x;
        for (let i = 1; i < data.length; i++) {
            if (data[i].x < this.posX) {
                this.posX = data[i].x;
            }
            if (this.posY < data[i].y) {
                this.posY = data[i].y
            }
            if (x1 != data[i].x) {
                isX = false;
            }
            if (x2 != data[i].y) {
                isY = false;
            }
        }

        success(data, isX, isY);
    }

    private checkDown(isX, isY) {

        if (isY) {
            //横向消除
            for (let i = 0; i < 4; i++) {
                for (let j = 1; j < this.GRID_HEIGHT - this.posY; j++) {
                    if (this.cells[this.posX + i][this.posY + j] == "") {
                        continue
                    }
                    // let ac: cc.ActionInterval = cc.moveBy(0.5, new cc.Vec2(this.cellsNode[this.posX + i][this.posY + j].x, -this.CELL_HEIGHT))
                    // this.cellsNode[this.posX + i][this.posY + j].runAction(cc.spawn)
                    let node = this.cellsNode[this.posX + i][this.posY + j]
                    cc.tween(node).by(0.5, { y: -this.CELL_HEIGHT }).delay(0.1).call(() => {
                        // node.getComponent(UIXiaoxiaoleItem).updatePos();

                        let temp = this.cellsNode[this.posX + i][this.posY + j]
                        this.cellsNode[this.posX + i][this.posY + j - 1] = temp
                        this.cellsNode[this.posX + i][this.posY + j] = null;
                        let temp1 = this.cells[this.posX + i][this.posY + j]
                        this.cells[this.posX + i][this.posY + j - 1] = temp1
                        this.cells[this.posX + i][this.posY + j] = "";
                    }).start();

                }
            }

        }
        if (isX) {
            //竖向消除
            for (let j = 1; j < this.GRID_HEIGHT - this.posY; j++) {
                if (this.cells[this.posX][this.posY + j] == "") {
                    continue
                }
                let node = this.cellsNode[this.posX][this.posY + j];
                cc.tween(node).by(0.5, { y: -this.CELL_HEIGHT * 4 }).delay(0.1).call(() => {
                    // node.getComponent(UIXiaoxiaoleItem).updatePos();

                    let temp = this.cellsNode[this.posX][this.posY + j]
                    this.cellsNode[this.posX][this.posY + j - 4] = temp
                    this.cellsNode[this.posX][this.posY + j] = null;
                    let temp1 = this.cells[this.posX][this.posY + j]
                    this.cells[this.posX][this.posY + j - 4] = temp1
                    this.cells[this.posX][this.posY + j] = ""
                }).start();

            }
        }
        setTimeout(() => {
            this.finfishCallBack && this.finfishCallBack(this.cells);
        }, 700);

    }

    private selectCell(pos: cc.Vec2): cc.Node {
        if (cc.isValid(this.cellsNode[pos.x][pos.y])) {
            return this.cellsNode[pos.x][pos.y]
        }
    }


    /**
     * 
     * @param fangxiang 方向 LR OR  UD
     * @param num 词组多长
     */
    private addList(fangxiang, list, data) {
        if (fangxiang == "LR") {

            for (let i = 0; i < data.length; i++) {
                let h = this.searchHeight(list);
                this.cells[list][h] = data[i]
                list++;
                //console.log(`w:${list} h:${h}  value: ${data[i]}`)
            }
        } else {
            let h = this.searchHeight(list);
            for (let i = 0; i < data.length; i++) {
                this.cells[list][h] = data[i]
                h += 1;
                //console.log(`w:${list} h:${h}  value: ${data[i]}`)
            }
        }

    }

    private searchHeight(w) {
        let value = null;
        try {

            for (let i = 0; i < this.GRID_HEIGHT; i++) {
                if (this.cells[w][i] == "") {
                    // return i
                    value = i;
                    break;
                }
            }
        } catch {

        }
        if (value == null) {
            // console.log("w    ", w)
        }


        return value;
    }

    private searchLow(r) {
        let left = false;
        let right = false;

        if (this.cells[r - 1] && this.cells[r - 1][0] != "") {
            left = true;
        }
        if (this.cells[r + 1] && this.cells[r + 1][0] != "") {
            right = true;
        }
        // if (r == 0) {
        //     left = false;
        // }
        // if (r == this.GRID_WIDTH) {
        //     right = false;
        // }
        if(!left && !right){
            console.log(`r: ${r}  左右空  重新来`)
        }
        
        return left || right
    }

    private shuffle(arr) {
        let i = arr.length;
        while (i) {
            let j = Math.floor(Math.random() * i--);
            [arr[j], arr[i]] = [arr[i], arr[j]];
        }
        return arr;
    }


    private initList() {
        this.shuxiangChao = []
        for (let i = 0; i < this.GRID_HEIGHT; i++) {
            this.shuxiangChao.push(i);
        }
        this.henxiangChao = []
        for (let i = 0; i < this.GRID_WIDTH; i++) {
            this.henxiangChao.push(i);
        }
    }

    private searchList(h) {
        let isOk = true;
        for (let i = h; i < this.GRID_WIDTH; i++) {
            if (this.cells[i][this.GRID_HEIGHT - 1] != "") {
                isOk = false;
                break;
            }
        }
        return isOk
    }

}
